package com.mt.mall.service.good.impl;

import com.mt.common.core.utils.ESUtil;
import com.mt.mall.dao.good.SpecificationStockDao;

import com.mt.common.core.exception.BusinessException;
import com.mt.common.core.web.base.PageDTO;
import com.mt.common.core.web.base.PageResultDTO;
import com.mt.common.core.web.base.BaseEntity;
import com.mt.common.core.web.BaseService;
import com.mt.mall.entity.good.Commodity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mt.mall.entity.good.SpecificationStock;
import com.mt.mall.service.good.SpecificationStockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.persistence.Index;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@Transactional
public class SpecificationStockServiceBean extends BaseService implements SpecificationStockService {

    private static Logger logger = LogManager.getLogger();

	@Autowired
	private SpecificationStockDao specificationStockDao;

	@Resource
	private RedisTemplate<String, List<SpecificationStock>> redisTemplate;

	@Autowired
	StringRedisTemplate stringRedisTemplate;

	/**
	 * 根据分页参数查询商品销售规格集合
	 *
	 * @param pageDTO 分页条件
	 */
	@Override
	public PageResultDTO findSpecificationStocks(PageDTO pageDTO){
        pageDTO.setStartIndex((pageDTO.getCurrentPage()-1)*pageDTO.getPageSize());
		//TODO:请在此校验参数的合法性
		this.validateFindSpecificationStocks(pageDTO);
		if(this.getStoreId()!=-1){
			pageDTO.getFilters().put("shopId",this.getStoreId());
			pageDTO.getFilterTypes().put("shopId","单值");
		}
		List<SpecificationStock> specificationStockDTOS = this.specificationStockDao.findSpecificationStocks(pageDTO);
		Long totalCount = this.specificationStockDao.findSpecificationStockTotalCount(pageDTO);

		PageResultDTO pageResultDTO = new PageResultDTO();
		pageResultDTO.setTotalCount(totalCount);
		pageResultDTO.setDatas(specificationStockDTOS);

		return pageResultDTO;
	}

	/**
	 * 查询全部商品销售规格集合
	 *
	 */
	@Override
	public List<SpecificationStock> findAllSpecificationStocks(){
		return this.specificationStockDao.findAllSpecificationStocks();
	}

	/**
	 * 查询所有商品销售规格集合(只提取ID 和 Name)
	 *
	 */
	@Override
	public List<SpecificationStock> findAllSpecificationStocksWithIdName(){
		//TODO:请在此校验参数的合法性
		this.validateFindAllSpecificationStocksWithIdName();
		return this.specificationStockDao.findAllSpecificationStocksWithIdName();
	}

	/**
	 * 根据名称查询商品销售规格集合(只提取ID 和 Name)
	 *
	 * @param specificationStockName 名称
	 */
	@Override
	public List<SpecificationStock> findSpecificationStocksWithIdNameByName(String specificationStockName){
		//TODO:请在此校验参数的合法性
		this.validateFindSpecificationStocksWithIdNameByName(specificationStockName);
		//TODO:缓存取对应参数
		Set<String> keys = stringRedisTemplate.keys("searchData:SpecificationStock_where_specificationStockName_" + specificationStockName);
		List<SpecificationStock> specificationStocks = new ArrayList<>();
		if (keys.isEmpty()) {
		specificationStocks = this.specificationStockDao.findSpecificationStocksWithIdNameByName(specificationStockName);
		redisTemplate.opsForValue().set("searchData:SpecificationStock_where_specificationStockName_" + specificationStockName, specificationStocks, 30, TimeUnit.DAYS);
		} else {
		specificationStocks = redisTemplate.opsForValue().get("searchData:SpecificationStock_where_specificationStockName_" + specificationStockName);
		}
		return specificationStocks;
	}

	/**
	 * 根据ID查询指定的商品销售规格(只提取ID 和 Name)
	 *
	 * @param specificationStockId Id
	 */
	@Override
	public SpecificationStock findSpecificationStocksWithIdNameById(Long specificationStockId){
		//TODO:请在此校验参数的合法性
		this.validateFindSpecificationStocksWithIdNameById(specificationStockId);
		return this.specificationStockDao.findSpecificationStocksWithIdNameById(specificationStockId);
	}

	/**
	 * 根据ID查询指定的商品销售规格
	 *
	 * @param specificationStockId Id
	 */
	@Override
	public SpecificationStock findSpecificationStock(Long specificationStockId){
		//TODO:请在此校验参数的合法性
		this.validateFindSpecificationStock(specificationStockId);
		return this.specificationStockDao.findSpecificationStock(specificationStockId);
	}

	/**
	 * 根据ID查询指定的商品销售规格(包含外键)
	 *
	 * @param specificationStockId Id
	 */
	@Override
	public SpecificationStock findSpecificationStockWithForeignName(Long specificationStockId){
		//TODO:请在此校验参数的合法性
		this.validateFindSpecificationStockWithForeignName(specificationStockId);
		return this.specificationStockDao.findSpecificationStockWithForeignName(specificationStockId);
	}

	/**
	 * 新增商品销售规格
	 *
	 * @param specificationStock 实体对象
	 */
	@Autowired
	ESUtil esUtil;
	private String INDEX_NAME = "commodity";
	@Override
	public SpecificationStock saveSpecificationStock(SpecificationStock specificationStock){
		//TODO:请在此校验参数的合法性
		this.validateSaveSpecificationStock(specificationStock);
		//TODO:填充公共参数
		this.setSavePulicColumns(specificationStock);

		Long count=this.specificationStockDao.findSpecificationStocksCount(specificationStock.getCommodityId(),specificationStock.getSpecification());
		if(count>0){
			throw new BusinessException("当前商品的规格已经存在了，请添加其他规格");
		}

		Commodity commodity=esUtil.selectDocumentById(INDEX_NAME,String.valueOf(specificationStock.getCommodityId()),Commodity.class);

		if(commodity.getMinPrice()==null||commodity.getMinPrice()>specificationStock.getPrice()){
			commodity.setMinPrice(specificationStock.getPrice());
			esUtil.insertDocument(INDEX_NAME,commodity);
		}

		specificationStock.setShopId(this.getStoreId());
		Long rows = this.specificationStockDao.saveSpecificationStock(specificationStock);
		if(rows != 1)
		{
			String error = "新增保存商品销售规格出错，数据库应该返回1,但返回了 "+rows;
			throw new BusinessException(error);
		}
		return specificationStock;
	}

	/**
	 * 更新商品销售规格
	 *
	 * @param specificationStock 实体对象
	 */
	@Override
	public SpecificationStock updateSpecificationStock(SpecificationStock specificationStock){
		//TODO:请在此校验参数的合法性
		this.validateUpdateSpecificationStock(specificationStock);
		Long rows = this.specificationStockDao.updateSpecificationStock(specificationStock);
		if(rows != 1)
		{
			String error = "修改保存商品销售规格出错，数据库应该返回1,但返回了 "+rows+",数据可能被删除";
			throw new BusinessException(error);
		}
		return specificationStock;
	}

	/**
	 * 根据ID删除商品销售规格
	 *
	 * @param specificationStockId ID
	 */
	@Override
	public void deleteSpecificationStock(Long specificationStockId){
		//TODO:请在此校验参数的合法性
		this.validateDeleteSpecificationStock(specificationStockId);

		Map<Class<? extends BaseEntity>,EntityUsage> entityUsageMap = this.checkForeignEntity(SpecificationStock.class, specificationStockId);
		if(entityUsageMap != null && entityUsageMap.size() >0){
			StringBuilder errors = new StringBuilder();
			errors.append("计划删除的数据正在被以下数引用\n");
			for(EntityUsage entityUsage : entityUsageMap.values()){
				errors.append("\t").append(entityUsage.getEntityLabel()).append("\n");
				for(Map.Entry<Long,String> entry : entityUsage.getUsageIdNames().entrySet() ){
					errors.append("\t\t").append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
				}
			}
			errors.append("，不能删除，请检查处理后再删除");
			throw  new BusinessException(errors.toString());
		}

		Long rows = this.specificationStockDao.deleteSpecificationStock(specificationStockId);
		if(rows != 1){
			String error = "删除商品销售规格出错，数据可能已经被删除";
			throw new BusinessException(error);
		}
	}

	@Override
	public List<SpecificationStock> findSpecificationStockByCommodityId(Long commodityId) {
		return this.specificationStockDao.findSpecificationStockByCommodityId(commodityId);
	}

	@Override
	public Long decrStock(Long commodityId, String specification, Integer count) {
		return this.specificationStockDao.decrStock(commodityId,specification,count);
	}

	@Override
	public Integer getStock(Long commodityId, String specification) {
		return this.specificationStockDao.getStock(commodityId,specification);
	}

	@Override
	public int incrStock(Long commodityId, String specification, Integer count) {
		return this.specificationStockDao.incrStock(commodityId,specification,count);
	}

	//TODO:---------------验证-------------------

	private void validateFindSpecificationStocks(PageDTO pageDTO) {
	//TODO:请使用下面方法添加数据过滤条件
	//		pageDTO.addFilter("creatorId",this.getLoginUserId());
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	private void validateFindSpecificationStocksWithIdNameByName(String specificationStockName) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}


	private void validateFindAllSpecificationStocksWithIdName() {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	private void validateFindSpecificationStocksWithIdNameById(Long specificationStockId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	private void validateFindSpecificationStock(Long specificationStockId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	private void validateFindSpecificationStockWithForeignName(Long specificationStockId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	private void validateSaveSpecificationStock(SpecificationStock specificationStock) {
	//不为空判断
	if (specificationStock.getEid() != null || specificationStock.getCreatorId() != null || specificationStock.getCreateDatetime() != null) {
	throw new BusinessException("非法请求");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	private void validateUpdateSpecificationStock(SpecificationStock specificationStock) {
	//不为空判断
	if (specificationStock.getEid() == null) {
	throw new BusinessException("唯一标识不能为空");
	}
	//是否存在判断
	if (this.specificationStockDao.findSpecificationStockTotalCount(PageDTO.create(SpecificationStock.FIELD_ID, specificationStock.getEid())) == 0) {
	throw new BusinessException("修改的商品销售规格 " + specificationStock.getName() + " 不存在，修改失败，请重试或联系管理员");
	}
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	private void validateDeleteSpecificationStock(Long specificationStockId) {
	//TODO:请完善数据校验规则和数据权限判断，如果有问题请抛出异常，参看下面validateUpdateSpecificationStock()写法
	}

	@Override
	public boolean canDownloadAttachment(String formName, Long id) {
	return true;
	}
}
